package com.bearingnavi.android.views;

import java.io.UnsupportedEncodingException;
import java.net.URLEncoder;

import android.app.Activity;
import android.content.Context;
import android.content.Intent;
import android.graphics.Point;
import android.util.Log;
import android.view.Display;
import android.view.MotionEvent;
import android.view.View;
import android.view.ViewGroup;
import android.widget.Button;
import android.widget.ImageView;
import android.widget.LinearLayout;
import android.widget.Toast;
import android.widget.RelativeLayout.LayoutParams;

import com.bearingnavi.android.R;
import com.bearingnavi.android.overlays.BearingOverlay;
import com.bearingnavi.android.overlays.MeasurementOverlay;
import com.bearingnavi.android.overlays.WayPointOverlay;
import com.bearingnavi.android.services.LocationService;
import com.bearingnavi.android.util.MarshalOverlay;
import com.bearingnavi.android.util.OverlayUtil;
import com.google.android.maps.GeoPoint;
import com.google.android.maps.MapView;
import com.google.android.maps.Overlay;
import com.google.android.maps.Projection;

public class LongpressPopupPanel {
	private static RelativePositionLayout wrapper;
	private static View popup;
//	private static boolean isVisible = false;
	private MapView map;
	private Context context;
	private Overlay closestOverlay;
	private GeoPoint geoPoint;

	public LongpressPopupPanel(Activity activity, MapView map) {
		this.map = map;
		this.context = activity;
		
		setup(activity);
	}
	
	private void setup(Activity activity) {
		
		wrapper = new RelativePositionLayout(activity);
		popup = activity.getLayoutInflater().inflate(R.layout.longpress, map, false);
		popup.setOnTouchListener(new View.OnTouchListener() {
			
			public boolean onTouch(View v, MotionEvent event) {
				return true; //when clicking on pop up content do not hide it.
			}
		});
		wrapper.setOnTouchListener(new View.OnTouchListener() {
			
			public boolean onTouch(View v, MotionEvent event) {
				hide(LongpressPopupPanel.this.map);
				return false;
			}
		});
		LayoutParams params =  new LayoutParams(LayoutParams.FILL_PARENT, LayoutParams.FILL_PARENT);
		activity.addContentView(wrapper, params);
		
		Button addBearing = (Button) popup.findViewById(R.id.addBearing);
		Button addWP = (Button) popup.findViewById(R.id.addWp);
		Button cleanBearing = (Button) popup.findViewById(R.id.cleanBearing);
		Button cleanWP = (Button) popup.findViewById(R.id.cleanWp);
		Button share = (Button) popup.findViewById(R.id.Share);
		Button measure = (Button) popup.findViewById(R.id.measure);
		Button cleanMeasure = (Button) popup.findViewById(R.id.cleanMeasure);
		addBearing.setOnClickListener(new View.OnClickListener() {
			
			public void onClick(View view) {
				OverlayUtil.drawBearingLine(map, context , null, true, geoPoint);
				hide(map);
			}
		});
		cleanBearing.setOnClickListener(new View.OnClickListener() {
			
			public void onClick(View view) {
				OverlayUtil.cleanBearingLine(map, context, ((BearingOverlay) closestOverlay).getIndex());
				hide(map);
			}
		});
		addWP.setOnClickListener(new View.OnClickListener() {
			
			public void onClick(View view) {
				OverlayUtil.addWayPoint(map, context, null, true, geoPoint);
				hide(map);
			}
		});
		cleanWP.setOnClickListener(new View.OnClickListener() {
			
			public void onClick(View view) {
				OverlayUtil.cleanWaypoint(map, context, ((WayPointOverlay) closestOverlay).getIndex());
				hide(map);
			}
		});
		share.setOnClickListener(new View.OnClickListener() {
			
			public void onClick(View view) {
				shareOverlay();
			}
		});
		measure.setOnClickListener(new View.OnClickListener() {
			
			public void onClick(View view) {
				LocationService.setDestGeoPoint(geoPoint);
				map.invalidate();
				hide(map);
			}
		});
		cleanMeasure.setOnClickListener(new View.OnClickListener() {
			
			public void onClick(View view) {
				LocationService.setDestGeoPoint(null);
				map.invalidate();
				hide(map);
			}
		});
	}
	
	private void getPointFromOverlay(WayPointOverlay wp, Point point){
		GeoPoint gp = wp.getGeoPoint();
		Projection projection = map.getProjection();
		point = projection.toPixels(gp, point);
	}
	
	public void show(GeoPoint geoPoint, Point point, Overlay closestOverlay) {
		hide(map);//Hide in case it's showed some where.
		this.closestOverlay = closestOverlay;
		this.geoPoint = geoPoint;
		LocationService.setHoldMap(true);
		int fingerX = (int) wrapper.getCurrentX();
		int fingerY = (int) wrapper.getCurrentY();
		Projection projection = map.getProjection();
		
		buildUI();
		setPopUpDimenssions();
		ViewGroup.LayoutParams popupParams = popup.getLayoutParams();
		Display display = ((Activity) context).getWindowManager().getDefaultDisplay();
		int screenWidth = display.getWidth();
		
		float angle = (float) Math.toRadians(RotateView.getInstance().getBearing());
		float cosA = android.util.FloatMath.cos(angle);
		float sinA = android.util.FloatMath.sin(angle);
		
		int mapCenter = map.getHeight()/2; // the map is a square 1077x1077px. center is (538,538)
		int arrowWidth = 32;  // arrow image under the pop-up window
		
		int top = 0; // how much we need to move the map UP, in case the pop-up window is cropped out from the top of the screen 
		
		
		if (closestOverlay instanceof WayPointOverlay){
			int fX = point.x, fY = point.y;
			getPointFromOverlay( (WayPointOverlay) closestOverlay, point);
			this.geoPoint = projection.fromPixels(point.x, point.y);
			fingerX += (point.x - fX) * cosA + (point.y - fY) * sinA;
			fingerY += (point.y - fY) * cosA - (point.x - fX) * sinA;
		}
		
		
		int xCenter = (int) ((point.x - mapCenter) * sinA);
		int yCenter = (int) ((point.y - mapCenter) * cosA);
		int distAboveCenter = (int) Math.sqrt(xCenter*xCenter + yCenter*yCenter);
		
		if ((mapCenter - distAboveCenter) < (popupParams.height)) {
			top = (popupParams.height) - (mapCenter - distAboveCenter);
		}
		
		
		final LayoutParams params =  new LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT);
		params.leftMargin = fingerX - (int) (popupParams.width * 0.5f);
		params.topMargin = fingerY - popupParams.height;
		
		
			
		// check if the pop-up window isn't cropped out of the screen
		// else, correct its position to be inside the screen
		if (params.leftMargin < 0) {
			params.leftMargin = 0;
		}
		else if (params.leftMargin + popupParams.width > screenWidth){
			params.leftMargin = screenWidth - popupParams.width;
		}
	
		if (params.topMargin < 0) {
			top = -params.topMargin;
			params.topMargin = 0;
		}
		
		
		// calculate how much we want to move the map. a = x axis, b = y axis
		int a = (int) (top * sinA);
		int b = (int) (top * cosA);
		
		geoPoint = projection.fromPixels(mapCenter + a,mapCenter - b);
		
		
		LinearLayout.LayoutParams arrowParams = new LinearLayout.LayoutParams(
				LinearLayout.LayoutParams.WRAP_CONTENT,
				LinearLayout.LayoutParams.WRAP_CONTENT);
		arrowParams.leftMargin = fingerX - params.leftMargin - arrowWidth/2;
		arrowParams.topMargin = -3;
		
		((ImageView)((LinearLayout)popup).getChildAt(1)).setLayoutParams(arrowParams);
		Log.d("LongPressPopUp", String.format("popup height: %d, width: %d", popup.getHeight(), popup.getWidth()));
		
		map.getController().animateTo(geoPoint, new Runnable() {
			
			public void run() {
				wrapper.addView(popup, params);
				LocationService.setHoldMap(true);
				map.setClickable(false);
			}
		});
	}
	
	private void setPopUpDimenssions() {
		ViewGroup.LayoutParams layoutParams = new ViewGroup.LayoutParams(popup.getLayoutParams());
		
		if (closestOverlay == null) {
			layoutParams.width = 152;
			layoutParams.height = 181;
		} else if (closestOverlay instanceof WayPointOverlay) {
			layoutParams.width = 218;
			layoutParams.height = 181;
		} else if (closestOverlay instanceof BearingOverlay) {
			layoutParams.width = 218;
			layoutParams.height = 181;
		} else if (closestOverlay instanceof MeasurementOverlay) {
			layoutParams.width = 218;
			layoutParams.height = 115;
		}
		
		popup.setLayoutParams(layoutParams);
	}
	
	private void buildUI() {
		LinearLayout cleanCon = (LinearLayout) popup.findViewById(R.id.CleanContainer);
		Button addBearing = (Button) popup.findViewById(R.id.addBearing);
		Button addWP = (Button) popup.findViewById(R.id.addWp);
		Button cleanBearing = (Button) popup.findViewById(R.id.cleanBearing);
		Button cleanWP = (Button) popup.findViewById(R.id.cleanWp);
		Button share = (Button) popup.findViewById(R.id.Share);
		Button cleanMeasure = (Button) popup.findViewById(R.id.cleanMeasure);
		
		share.setVisibility(View.VISIBLE);
		cleanCon.setVisibility(View.VISIBLE);
		addWP.setVisibility(View.VISIBLE);
		cleanBearing.setVisibility(View.VISIBLE);
		addBearing.setVisibility(View.VISIBLE);
		cleanWP.setVisibility(View.VISIBLE);
		cleanMeasure.setVisibility(View.VISIBLE);
		
		if (closestOverlay == null) {
			
			share.setVisibility(View.GONE);
			cleanCon.setVisibility(View.GONE);
			
		} else if (closestOverlay instanceof WayPointOverlay) {
			
			addWP.setVisibility(View.GONE);
			cleanBearing.setVisibility(View.GONE);
			cleanMeasure.setVisibility(View.GONE);
			
		} else if (closestOverlay instanceof BearingOverlay) {
			
			addBearing.setVisibility(View.GONE);
			cleanWP.setVisibility(View.GONE);
			cleanMeasure.setVisibility(View.GONE);
			
		} else if (closestOverlay instanceof MeasurementOverlay) {
		
			share.setVisibility(View.GONE);
			addBearing.setVisibility(View.GONE);
			cleanWP.setVisibility(View.GONE);
			cleanBearing.setVisibility(View.GONE);
		}
	}

	public static boolean hide(MapView mapView) {
		View view = wrapper.getChildAt(0);
		if (view != null) {
			wrapper.removeView(view);
			LocationService.setHoldMap(false);
			mapView.setClickable(true);
			return true;
		}
		return false;
	}
	
	private void shareOverlay() {
		String objectData = ((MarshalOverlay)closestOverlay).marshal();
		String url = "http://bearingnavi.com/";
		
		if (objectData != null) {
			try {
				url += URLEncoder.encode(closestOverlay.getClass().getName() + MarshalOverlay.FIELDS_SEPARATOR, "utf-8");
				url += URLEncoder.encode(objectData + MarshalOverlay.OBJECTS_SEPARATOR, "utf-8");
			} catch (UnsupportedEncodingException e) {}
		}
		
		Intent i = new Intent(Intent.ACTION_SEND);
		i.setType("text/plain");
		i.putExtra(Intent.EXTRA_TEXT, url);
		try {
		    context.startActivity(Intent.createChooser(i, "Send with:"));
		} catch (android.content.ActivityNotFoundException ex) {
			Toast.makeText(context, "There are no email clients installed.", Toast.LENGTH_SHORT).show();
		}
	}
	
}